<?php
/**
 * Pert Library
 * File Class
 *
 * @author	Emre Hasegeli <hasegeli@gmail.com>
 * @license	GNU General Public License v3
 */

namespace Pert;

interface iFile
{
	const maxNameLength = 60;

	public function __toString();

	public function Name();

	public function Extension();

	public function Size();

	public function Move($directory);

	public function Rename($name);

	public function Delete();
}

class FileException extends \Exception
{
}

class File implements iFile
{
	private $directory;

	private $name;

	private $extension;

	public function __construct($directory, $name, $extension)
	{
		$this->directory = $directory;

		$this->name = $name;

		$this->extension = $extension;
	}

	public function __toString()
	{
		return $this->name . '.' . $this->extension;
	}

	public function Name()
	{
		return $this->name;
	}

	public function Extension()
	{
		return $this->extension;
	}

	final public function Size()
	{
		return filesize($this->directory . $this->name . '.' . $this->extension);
	}

	public function Copy($directory)
	{
		if(copy($this->directory . $this->name . '.' . $this->extension, $this->directory . $directory . $this->name . '.' . $this->extension))
			return new self($this->directory = $this->directory . $directory, $this->name, $this->extension);
		else
			throw new FileException('The file can not copied.');
	}

	public function Move($directory)
	{
		if(rename($this->directory . $this->name . '.' . $this->extension, $this->directory . $directory . $this->name . '.' . $this->extension))
			$this->directory = $this->directory . $directory;
		else
			throw new FileException('The file can not moved.');
	}

	final public function Address()
	{
		return $this->directory . $this->name . '.' . $this->extension;
	}

	public function Delete()
	{
		if(unlink($this->Address()))
			unset($this);
		else
			throw new FileException('The file can not deleted.');
	}

	final public function Rename($name)
	{
		$name = File::NameCheck($name);

		if(rename($this->directory . $this->name . '.' . $this->extension, $this->directory . $name . '.' . $this->extension))
			$this->name = $name;
		else
			throw new FileException('The file can not renamed.');
	}

	public static function Select($directory, $name, $extension)
	{
		if(file_exists($directory . $name . '.' . $extension))
			return new self($directory, $name, $extension);
	}

	public static function NameCheck($name)
	{
		if(strlen($name) > self::maxNameLength)
			throw new FileException('The file\'s name is too long');

		$name = str_replace('ı', 'i', $name);
		$name = str_replace('İ', 'I', $name);
		$name = str_replace('ü', 'u', $name);
		$name = str_replace('Ü', 'U', $name);
		$name = str_replace('ö', 'o', $name);
		$name = str_replace('Ö', 'O', $name);
		$name = str_replace('ğ', 'g', $name);
		$name = str_replace('Ğ', 'G', $name);
		$name = str_replace('ş', 's', $name);
		$name = str_replace('Ş', 'S', $name);
		$name = str_replace('ç', 'c', $name);
		$name = str_replace('Ç', 'C', $name);

		$name = trim($name, " .,;+-");

		$name = str_replace(' ', '_', $name); // substitute the spaces
		$name = str_replace('-', '_', $name); // substitute the hyphens
		$name = preg_replace('/[^a-zA-Z0-9_!\'().,;+-]/', '', $name); //remove all non-alphanumeric characters except some symbols

		return $name;
	}

	public static function ExtensionCheck($extension)
	{
		if(!$extension)
			throw new FileException('The file does not have an extension.');

		if(strlen($extension) > 5)
			throw new FileException('The file\'s extension is too long');

		$extension = strtolower($extension);
		$extension = preg_replace('/[^a-zA-Z0-9_!\'().,;+&-]/', '', $extension); //remove all non-alphanumeric characters except some symbols

		return $extension;
	}
}
